import { listContainerReq } from '@/api/docker'
import { DescribeInstancesOpenstackDocument } from '@/generated/graphql'
import { urqlOptions } from '@/plugins/urql'
import { Route, router } from '@/router'
import { useNFS } from '@/stores/nfs'
import { DLog } from '@/utils/log'
import { Client, createClient } from '@urql/vue'
import { message, Modal } from 'ant-design-vue'
import { intersection, isEqual } from 'lodash-es'
import { catchError, from, interval, lastValueFrom, of, switchMap, takeWhile } from 'rxjs'
import { Router } from 'vue-router'
import { OpenstackServices } from './openstackServices'

export interface BindSession {
  tags: string[]
  backends: Record<string, any>
  createSessionData: {
    courseId: string
    documentId: string
  }
}

class OpenstackSession {
  openstack: OpenstackServices
  client: Client
  nfsStore
  router

  constructor(openstack: OpenstackServices, router: Router) {
    this.openstack = openstack
    this.client = createClient(urqlOptions)
    this.nfsStore = useNFS()
    this.router = router
  }

  //检查实例状态 data.describeInstances_openstack[0].info.status == "ACTIVE"
  async CheckInstanceStatus(instanceId: string) {
    return await this.client
      .mutation(DescribeInstancesOpenstackDocument, {
        data: {
          InstanceIds: [instanceId]
        }
      })
      .toPromise()
  }

  //检查实例是否开启
  CheckInstanceStart(instanceId: string) {
    return interval(3000).pipe(
      switchMap(() => from(this.CheckInstanceStatus(instanceId))),
      takeWhile((data: any) => {
        DLog.Info('查看实例情况', data)
        return data.data.describeInstances_openstack[0].info.status != 'ACTIVE'
      }),
      catchError((e) => of(e))
    )
  }

  //检查docker api是否能够连接
  // async CheckDockerAPIAlive() {
  //   try {
  //     await listContainerReq()
  //   } catch (e) {
      
  //     DLog.Error('docker api连接出错', e)
  //     //这里需要多执行几次，如果连接出错重新执行
  //     setTimeout(() => {
  //       this.CheckDockerAPIAlive()
  //     }, 2000)
  //   }
  // }
  // 我改后:检查docker api是否能够连接
  async CheckDockerAPIAlive(retryCount = 0) {
    try {
      await listContainerReq();
    } catch (e) {
      if (retryCount < 15) {
        // 重试次数不超过5次时，增加重试次数并延迟1秒后再次执行 CheckDockerAPIAlive()
        await new Promise(resolve => setTimeout(resolve, 3000));
        await this.CheckDockerAPIAlive(retryCount + 1);
      }else{
        // message.error('docker api连接出错,请联系管理员!')
        DLog.Error('docker api连接出错', e)
      }
    }
  }
  //重新绑定session
  async ReBindSession(sessionId: string, data: BindSession) {
    await this.openstack.delete_one_session({
      id: sessionId,
      force: true
    })
    await this.BindSession(data)
  }

  //绑定session
  async BindSession(data: BindSession) {
    //绑定虚拟池
    console.log(data);
    const services = await this.openstack.private_instance_nearby(data.tags)

    if (services.error) {
      message.error(services.error.message)
      throw new Error(services.error.message)
    }

    if (services.data?.private_instance_nearby.records[0].instances.length <= 0) {
      message.error('虚拟池资源已满,请联系管理员!')
      await router.replace({ name: Route.COMPETITION })
      router.go(0)
      throw new Error('虚拟池资源已满,请联系管理员!')
    }

    //获取到docker的router
    let routerPath: string = '/docker-remote-api'
    routerPath =
      services.data?.private_instance_nearby.records[0]?.instances[0]?.info?.addresses['network-public'][0].addr
    const privateId = services.data?.private_instance_nearby.records[0].instances[0].id

    // 实例信息和课程ID信息写入本地
    this.nfsStore.setNFSState({ documentId: data.createSessionData.documentId, instanceId: privateId })

    await this.openstack.create_one_session({
      //这个只是绑定session 用于标识那个资源在使用
      ...data.createSessionData,
      duration: 1,
      termiate: 1,
      environment: {},
      backends: [
        {
          platformType: 'PRIVATE',
          data: {
            instanceRealId: privateId,
            ...data.backends
          }
        }
      ]
    })

    // 检查实例开启
    const checkStart = await lastValueFrom(this.CheckInstanceStart(privateId), { defaultValue: '' })
    DLog.Info('实例开启检查结果', checkStart)
    const errorReg = new RegExp('error', 'i')
    if (errorReg.test(checkStart)) {
      //说明存在错误了
      DLog.Error('实例开启检查出错', checkStart)
      this.router.go(0)
      message.error('出错了!')
      throw new Error(checkStart)
    }

    if (/windows/.test(data.tags.join(','))) {
      // windows 环境
      return { type: 'windows', routerPath }
    } else {
      console.log("doker环境");
      
      // docker 环境
      await this.CheckDockerAPIAlive()
    }

    return { type: 'linux', routerPath }
  }

  //弹窗展示, 让用户确认接下来的操作
  ShowChangeModal(title: string, sessionId: string, data: BindSession, cb?: () => void) {
    Modal.confirm({
      title: () => title,
      onOk: async () => {
        await this.ReBindSession(sessionId, data)
      },
      onCancel: () => {
        cb?.()
      }
    })
  }

  //比较标签信息
  CompareTags(sourceTags: string[], compareTags: string[]): boolean {
    const _interSectionArr = intersection(sourceTags, compareTags)
    return isEqual(_interSectionArr, compareTags)
  }
}

export { OpenstackSession }
